#include <stdio.h>
#include <stdlib.h>
#include "mpi.h"

/*
 * \author James Edmondson. Template taken from Brian Sulcer's test_waitall
 * \brief Tests MPI_WaitSome
 */

int main(int argc, char **argv)
{
	int size, rank, i, inbuf, outbuf;
	int success = 1;
	int completed = 0;
	int odds = 0;
	int * indices;
	MPI_Request *requests;
	MPI_Status *statuses;

	MPI_Init(&argc, &argv);
	
	MPI_Comm_size(MPI_COMM_WORLD, &size);
	MPI_Comm_rank(MPI_COMM_WORLD, &rank);
	
	if( size < 3 )
	{
		printf("Please run this program with more than 2 processes.\n");
		exit(1);
	}
	
	odds = size / 2;
	
	if (rank == 0)
	{
		outbuf = 4;
		indices = (int *)malloc((size - 1) * sizeof(int));
		requests = (MPI_Request *) malloc((size - 1) * sizeof(MPI_Request));
		statuses = (MPI_Status *) malloc((size - 1) * sizeof(MPI_Status));
		for (i = 1; i < size; i++)
		{
			if (i == rank) continue;
			if( i % 2 == 1 )
			{
				MPI_Isend(&outbuf, 1, MPI_INT, i, 1, 
						MPI_COMM_WORLD, requests + (i - 1));
			}
			else
			{
				requests[i-1] = MPI_REQUEST_NULL;
			}
		}
		fprintf(stderr,"About to Wait.\n");
		MPI_Waitsome(size - 1, requests, &completed, indices, statuses);
		MPI_Waitall(size - 1, requests, statuses);
		fprintf(stderr,"%d completed with WaitSome.\n", completed);
		if( completed >= 1 && completed <= odds )
		{
			printf("SUCCESS.\n");
		}
		else
		{
			printf("FAILURE.\n");
		}
	}
	else
	{
		if( rank % 2 == 1 )
		{
			fprintf(stderr,"Posting Recv.\n");
			MPI_Recv(&inbuf, 1, MPI_INT, 0, 1, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
			success = success && (inbuf == 4);
		}
	}
	
	MPI_Finalize();

	if (success == 1) {
		printf("SUCCESS\n");
	}
	
	printf("rank %d finished\n", rank);
	return 0;
}

